//
//  TextFieldViewController.swift
//  DemoProject
//
//  Created by hao on 2018/7/18.
//  Copyright © 2018年 hao. All rights reserved.
//

import UIKit

class TextFieldViewController: BaseTableViewController {

    let disposeBag = DisposeBag()
    
    lazy var textField: UITextField = {
        let _text = UITextField()
        self.tableHeadView.addSubview(_text)
        _text.snp.makeConstraints({ (make) in
            make.center.equalTo(self.tableHeadView)
            make.width.equalTo(200)
            make.height.equalTo(34)
        })
//        _text.delegate = self
        _text.returnKeyType = .done
        _text.borderStyle = .roundedRect
        return _text
    }()
    
    lazy var textField2: UITextField = {
        let _text = UITextField()
        self.tableHeadView.addSubview(_text)
        _text.snp.makeConstraints({ (make) in
            make.centerX.width.height.equalTo(self.textField)
            make.bottom.equalTo(_label.snp.top).offset(-15)
        })
        _text.borderStyle = .roundedRect
        return _text
    }()
    
    lazy var _label : UILabel = {
        let label = UILabel()
        self.tableHeadView.addSubview(label)
        label.snp.makeConstraints { (make) in
            make.centerX.equalTo(textField)
            make.bottom.equalTo(textField.snp.top).offset(-15)
        }
        return label;
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.keyboardType = .default
        setupData()
//        _rxSwiftProperty()
//        _rxSwiftMonitor()
//        _listenForChangesToMultipleTextFieldContent()
        _eventListen()
    }
    
    private func _rxSwiftProperty() {
        let rxText = textField.rx.text
        // .orEmpty 可以将 String? 类型的 ControlProperty 转成 String，这样就不用再去解包
        rxText.orEmpty.asObservable().subscribe { print(info: "asObservable -> \($0)") }.disposed(by: disposeBag)
        
        // .subscribe { print(info: "changed -> \($0)") }
        rxText.orEmpty.changed.bind(to: _label.rx.text).disposed(by: disposeBag)
    }
    
    private func _rxSwiftMonitor() {
        // Throttling 是 RxSwift 的一个特性。因为有时当一些东西改变时，通常会做大量的逻辑操作。而使用 Throttling 特性，不会产生大量的逻辑操作，而是以一个小的合理的幅度去执行。比如做一些实时搜索功能时，这个特性很有用
        let rxText = textField.rx.text
        // 在主线程中操作，0.3秒内值若多次改变，取最后一次
        let input = rxText.orEmpty.asDriver().throttle(0.3)
        input.map { "当前已输入个数: \($0.count)" }.drive(_label.rx.text).disposed(by: disposeBag)
        
        // 创建按钮
        let button = UIButton(type:.system)
        self.tableHeadView.addSubview(button)
        button.setTitle("提交", for:.normal)
        button.snp.makeConstraints { (make) in
            make.centerX.equalTo(textField)
            make.top.equalTo(textField.snp.bottom).offset(15)
        }
        // 当输入的字符个数%2==0时可编辑，否则不可编辑
        input.map { $0.count%2 == 0 ? true : false }.drive(button.rx.isEnabled).disposed(by: disposeBag)
    }
    
    // 同时监听多个 textField 内容的变化（textView 同理）
    private func _listenForChangesToMultipleTextFieldContent() {
        textField2.placeholder = "请输入区号"
        textField.placeholder = "请输入号码"
        Observable.combineLatest(textField.rx.text.orEmpty, textField2.rx.text.orEmpty) { (text1, text2) -> String in
            // 将两个值合并
            return "你输入的值是: " + text2 + "-" + text1
        }.map { $0 }.bind(to: _label.rx.text).disposed(by: disposeBag)
    }
    
    /// 通过 rx.controlEvent 可以监听输入框的各种事件，且多个事件状态可以自由组合。除了各种 UI 控件都有的 touch 事件外，输入框还有如下几个独有的事件：
    /// editingDidBegin：开始编辑（开始输入内容）
    /// editingChanged：输入内容发生改变
    /// editingDidEnd：结束编辑
    /// editingDidEndOnExit：按下 return 键结束编辑
    /// allEditingEvents：包含前面的所有编辑相关事件
    // 订阅时 务必使用带参数的 subscribe(onNext:),不然只会初始化时执行一次，后面就接收不到事件或者回调时机错误
    private func _eventListen() {
        textField.rx.controlEvent([.editingDidBegin]).asObservable().subscribe(onNext: { print(info: "editingDidBegin -> 开始编辑内容!") }).disposed(by: disposeBag)
        textField.rx.controlEvent([.editingDidEnd]).asObservable().subscribe(onNext: { print(info: "editingDidEnd 编辑内容!") }).disposed(by: disposeBag)
        textField.rx.controlEvent([.editingChanged]).asObservable().subscribe(onNext: { print(info: "editingChanged 编辑内容!") }).disposed(by: disposeBag)
        textField2.placeholder = "请输入账户名"
        textField.placeholder = "请输入密码"
        
        //在用户名输入框中按下 return 键
        textField2.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] in
            self?.textField.becomeFirstResponder()
        }).disposed(by: disposeBag)
        
        //在密码输入框中按下 return 键
        textField.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] in
            self?.textField.resignFirstResponder()
        }).disposed(by: disposeBag)
    }
    
    private func setupData() {
        let titles = ["enablesReturnKeyAutomatically",
                      "borderStyle(边框样式)",
                      "background",
                      "placeholder",
                      "clearButtonMode(输入框中是否有个叉号)",
                      "secureTextEntry(是否密文输入)",
                      "autocorrectionType(是否纠错)",
                      "clearsOnBeginEditing",
                      "contentVerticalAlignment",
                      "adjustsFontSizeToFitWidth",
                      "keyboardType(键盘的样式)",
                      "autocapitalizationType(首字母是否大写)",
                      "returnKeyType(return键变成什么键)",
                      "keyboardAppearance(键盘外观)",
                      "leftView和rightView",
                      "editing",
                      "界面重写绘制行为",
                      "inputView(调整键盘)",
                      "delegate",
                      "通知"]
        
        let descArr = [
                       "默认为No,如果设置为Yes,文本框中没有输入任何字符的话，右下角的返回按钮是disabled的",
                       """
                        UITextBorderStyle.none：无边框
                        UITextBorderStyle.line：直线边框
                        UITextBorderStyle.roundedRect：圆角矩形边框
                        UITextBorderStyle.bezel：边线+阴影
                       """,
                       """
                        // UITextField 的背景，注意只有UITextBorderStyleNone的时候改属性有效
                        text.background = [UIImage imageNamed:@"pngName"];
                        设置enable为no时，textfield的背景
                        text.disabledBackground = [UIImage imageNamed:@"pngName"];
                       """,
                       "当输入框无输入内容时提示的内容",
                       """
                        textField.clearButtonMode
                        UITextFieldViewModeNever,　从不出现
                        UITextFieldViewModeWhileEditing, 编辑时出现
                        UITextFieldViewModeUnlessEditing,　除了编辑外都出现
                        UITextFieldViewModeAlways 　一直出现
                       """,
                       "每输入一个字符就变成点 用来输入密码时，设置这个属性",
                       """
                        text.autocorrectionType = UITextAutocorrectionTypeNo;
                        UITextAutocorrectionTypeDefault, 默认
                        UITextAutocorrectionTypeNo, 　不自动纠错
                        UITextAutocorrectionTypeYes,　自动纠错
                       """,
                       "再次编辑就清空 text.clearsOnBeginEditing = YES",
                       """
                        内容的垂直对齐方式 UITextField继承自UIControl,此类中有一个属性contentVerticalAlignment
                        text.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
                       """,
                       """
                        设置为YES时文本会自动缩小以适应文本窗口大小.默认是保持原来大小,而让长文本滚动
                        textFied.adjustsFontSizeToFitWidth = YES;
                        // 设置自动缩小显示的最小字体大小
                        text.minimumFontSize = 20;
                       """,
                       """
                        text.keyboardType = UIKeyboardTypeNumberPad;
                        UIKeyboardTypeDefault,     　默认键盘，支持所有字符
                        UIKeyboardTypeASCIICapable,　支持ASCII的默认键盘
                        UIKeyboardTypeNumbersAndPunctuation,　标准电话键盘，支持＋＊＃字符
                        UIKeyboardTypeURL,            URL键盘，支持.com按钮 只支持URL字符
                        UIKeyboardTypeNumberPad,      数字键盘
                        UIKeyboardTypePhonePad,　 　   电话键盘
                        UIKeyboardTypeNamePhonePad, 　电话键盘，也支持输入人名
                        UIKeyboardTypeEmailAddress, 　用于输入电子 邮件地址的键盘
                        UIKeyboardTypeDecimalPad,   　数字键盘 有数字和小数点
                        UIKeyboardTypeTwitter,      　优化的键盘，方便输入@、#字符
                        UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable,
                       """,
                       """
                        text.autocapitalizationType = UITextAutocapitalizationTypeNone;
                        UITextAutocapitalizationTypeNone, 不自动大写
                        UITextAutocapitalizationTypeWords,　单词首字母大写
                        UITextAutocapitalizationTypeSentences,　句子的首字母大写
                        UITextAutocapitalizationTypeAllCharacters, 所有字母都大写
                       """,
                       """
                        text.returnKeyType =UIReturnKeyDone;
                        UIReturnKeyDefault,     默认 灰色按钮，标有Return
                        UIReturnKeyGo,    　    标有Go的蓝色按钮
                        UIReturnKeyGoogle,      标有Google的蓝色按钮，用于搜索
                        UIReturnKeyJoin,        标有Join的蓝色按钮
                        UIReturnKeyNext,        标有Next的蓝色按钮
                        UIReturnKeyRoute,       标有Route的蓝色按钮
                        UIReturnKeySearch,      标有Search的蓝色按钮
                        UIReturnKeySend,        标有Send的蓝色按钮
                        UIReturnKeyYahoo,       标有Yahoo的蓝色按钮
                        UIReturnKeyEmergencyCall, 紧急呼叫按钮
                       """,
                       """
                        text.keyboardAppearance = UIKeyboardAppearanceDefault；
                        UIKeyboardAppearanceDefault，  默认外观，浅灰色
                        UIKeyboardAppearanceAlert，　 　深灰 石墨色
                       """,
                       """
                        // leftView同理
                        text.rightView = [[UIView alloc] init];
                        text.rightViewMode = UITextFieldViewModeAlways;
                        UITextFieldViewModeNever,
                        UITextFieldViewModeWhileEditing,
                        UITextFieldViewModeUnlessEditing,
                        UITextFieldViewModeAlways
                       """,
                       "是否允许编辑",
                       """
                        除了UITextField对象的风格选项，可以定制化UITextField对象，为他添加许多不同的重写方法，来改变文本字段的显示行为。这些方法都会返回一个CGRect结构，制定了文本字段每个部件的边界范围。以下方法都可以重写。
                        textRectForBounds:　　  　//重写来重置文字区域
                        drawTextInRect:　　      　//改变绘文字属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数，就不用调用super了.
                        placeholderRectForBounds:　　//重写来重置占位符区域
                        drawPlaceholderInRect:　　//重写改变绘制占位符属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数，就不用调用super了.
                        borderRectForBounds:　　//重写来重置边缘区域
                        editingRectForBounds:   //重写来重置编辑区域
                        clearButtonRectForBounds:   //重写来重置clearButton位置,改变size可能导致button的图片失真
                        leftViewRectForBounds:
                        rightViewRectForBounds:
                       """,
                       """
                        inputView //代替标准的系统键盘
                        inputAccessoryView //编辑时显示在系统键盘或用户自定义的inputView上面的视图
                       """,
                       """
                        类要遵守UITextFieldDelegate协议, text.delegate = self;
                        - (BOOL)textFieldShouldReturn:(UITextField *)textField
                        {
                            [text resignFirstResponder];    //主要是[receiver resignFirstResponder]在哪调用就能把receiver（text）对应的键盘往下收
                            return YES;
                        }

                        代理方法
                        - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
                            //返回一个BOOL值，YES代表允许编辑，NO不允许编辑.
                            return YES;
                        }

                        - (void)textFieldDidBeginEditing:(UITextField *)textField{
                            //开始编辑时触发，文本字段将成为first responder
                        }

                        - (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
                            //返回BOOL值，指定是否允许文本字段结束编辑，当编辑结束，文本字段会让出first responder
                        　  //要想在用户结束编辑时阻止文本字段消失，可以返回NO　，返回NO，点击键盘的返回按钮会无效果。
                        　  //这对一些文本字段必须始终保持活跃状态的程序很有用，比如即时消息
                            return NO;
                        }
                        - (void)textFieldDidEndEditing:(UITextField *)textField;{

                        }// 上面返回YES后执行;上面返回NO时有可能强制执行(e.g. view removed from window)

                        - (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
                            //当用户使用自动更正功能，把输入的文字修改为推荐的文字时，就会调用这个方法。
                            //这对于想要加入撤销选项的应用程序特别有用
                            //可以跟踪字段内所做的最后一次修改，也可以对所有编辑做日志记录,用作审计用途。
                            //要防止文字被改变可以返回NO
                            //这个方法的参数中有一个NSRange对象，指明了被改变文字的位置，建议修改的文本也在其中
                        
                        　   return YES;
                        }

                        - (BOOL)textFieldShouldClear:(UITextField *)textField{
                            //返回一个BOOL值指明是否允许根据用户请求清除内容
                            //可以设置在特定条件下才允许清除内容

                        　   return YES;
                        }

                        -(BOOL)textFieldShouldReturn:(UITextField *)textField{
                            //返回一个BOOL值，指明是否允许在按下回车键时结束编辑
                            //如果允许要调用resignFirstResponder 方法，这回导致结束编辑，而键盘会被收起[textField resignFirstResponder];
                            //查一下resign这个单词的意思就明白这个方法了
                        　   return YES;
                        }
                       """,
                       """
                        UITextFieldTextDidBeginEditingNotification
                        UITextFieldTextDidChangeNotification
                        UITextFieldTextDidEndEditingNotification
                        当文本字段退出编辑模式时触发。通知的object属性存储了最终文本。
                         
                        因为文本字段要使用键盘输入文字，所以下面这些事件发生时，也会发送动作通知
                        UIKeyboardWillShowNotification 　//键盘显示之前发送
                        UIKeyboardDidShowNotification  　//键盘显示之后发送
                        UIKeyboardWillHideNotification 　//键盘隐藏之前发送
                        UIKeyboardDidHideNotification  　//键盘隐藏之后发送
                       """]

        addTitles(titles, footDescs: descArr)
    }

}

extension TextFieldViewController: UITextFieldDelegate {
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // 收起键盘
        textField.resignFirstResponder()
        print(info: textField.text ?? "----")
        return true
    }
    
}

